// 聊天服务器和其他服务器的rpc通讯
class ChatRemote {
  constructor(app) {
    this.app = app
    this.channelService = app.get('channelService')
  }
}

// class 内部定义的函数不可枚举，无法导出，此写法可以避免。
Object.assign(ChatRemote.prototype, {
    /**
   * 将用户加入聊天通道
   * 
   * @param {String} uid 用户id
   * @param {String} sid 服务器id
   * @param {String} name 聊天通道名称 rid
   * @param {Boolean} flag 是否创建聊天通道
   * 
   */
  add(uid, sid, name, flag, cb) {
    const channel = this.channelService.getChannel(name, flag) // 获取通道信息
    const username = uid.split('*')[0] // 获取用户名
    const param = {
      route: 'onAdd', // 类似rpc通讯的监听名
      user: username
    }

    // 推送用户加入聊天室的消息，客户端监听 onAdd 得到讯息后，更新聊天室内用户列表
    channel.pushMessage(param)

    // 有通道时将该用户增加入通道
    if (!!channel) {
      channel.add(uid, sid)
    }

    // 回调返回用户uid数组
    cb(this.get(name, flag)) // 这里的 this 指向 ChatRemote 类
  },

  /**
   * 在聊天通道获得用户列表 - 为了用户第一次进入聊天室初始化聊天室内人员列表
   * 
   * @param {Object} opts requset 时的参数
   * @param {String} name 聊天通道名称 rid
   * @param {Boolean} flag 是否创建聊天通道
   * @return {Array} 返回用户uid数组
   */
  get(name, flag) {
    let users = []
    const channel = this.channelService.getChannel(name, flag) // 获取通道信息

    // 有通道时获得用户列表
    if (!!channel) {
      users = channel.getMembers()
    }

    // 循环获得用户名称
    users = users.map(el => {
      return el.split('*')[0]
    })
  
    return users
  },

  /**
   * 提出用户离开聊天室通道
   * 
   * @param {String} uid 用户id
   * @param {String} sid 服务器id
   * @param {String} name 聊天室通道
   * 
   */
  kick(uid, sid, name, cb) {
    const channel = this.channelService.getChannel(name, false) // 获取聊天室通道信息
    // 提出用户
    if (!!channel) {
      channel.leave(uid, sid)
    }
    const username = uid.split('*')[0]
    const param = {
      route: 'onLeave',
      user: username
    }
    channel.pushMessage(param) // 广播用户已经离开
    cb(null)
  }
})

module.exports = app => {
  return new ChatRemote(app)
}